<template>
  <el-card>
    <div style="margin-bottom: 10px">
      <el-cascader
        ref="cascader"
        v-model="zone"
        :options="zones"
        :props="{ expandTrigger: 'hover', emitPath: false, checkStrictly: true }"
        @change="onZoneChange"
        placeholder="选择分区"
        style="width: 180px"
      />
    </div>
    <div ref="chart" style="height: 600px"></div>
  </el-card>
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'
import * as echarts from 'echarts'
import { useApi } from '@/composables/useApi'
import partitionData from '@/assets/partition.json'

const http = useApi()

const chart = ref(null)
const cascader = ref(null)
let myChart = null
let timer = null

// 分区与默认值
const zones = partitionData
const zone = ref(0)

// 指标配置
const metrics = [
  { key: 'view', name: '播放量' },
  { key: 'danmaku', name: '弹幕数' },
  { key: 'reply', name: '评论数' },
  { key: 'like', name: '点赞数' },
  { key: 'coin', name: '投币数' },
  { key: 'favorite', name: '收藏数' },
  { key: 'count', name: '视频数' },
]

// Y 轴分组
const yAxisGroups = [
  { indices: [0], name: '播放量', color: '#337ab7' },
  { indices: [1], name: '弹幕数', color: '#5cb85c' },
  { indices: [2], name: '评论数', color: '#f0ad4e' },
  { indices: [3, 4, 5], name: '三连量', color: '#d9534f' },
  { indices: [6], name: '视频数', color: '#fb87aa' },
]

// 后端数据缓存
let allData = {}

function renderChart(currentStep = null) {
  const data = allData[zone.value] || []
  const weeks = data.map((item) => item.week)

  const displayData = currentStep ? data.slice(0, currentStep) : data
  const displayWeeks = currentStep ? weeks.slice(0, currentStep) : weeks

  const groupMaxValues = yAxisGroups.map((group) =>
    Math.max(
      ...group.indices.flatMap((idx) => {
        const metricKey = metrics[idx].key
        return displayData.map((item) => item[metricKey])
      }),
      0,
    ),
  )

  const option = {
    title: {
      text: `${cascader.value.getCheckedNodes()[0].label}分区周度数据`,
      left: 'center',
      top: 10,
    },
    tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } },
    legend: {
      data: metrics.map((m) => m.name),
      top: 40,
      left: 'center',
      type: 'scroll',
      orient: 'horizontal',
      width: '90%',
      itemGap: 15,
    },
    grid: { top: '18%', left: '8%', right: '18%', bottom: '5%', containLabel: true },
    xAxis: { type: 'category', data: displayWeeks, boundaryGap: true },
    yAxis: yAxisGroups.map((group, index) => {
      const maxVal = groupMaxValues[index]
      return {
        type: 'value',
        name: group.name,
        position: index === 0 ? 'left' : 'right',
        offset: index > 1 ? (index - 1) * 80 : 0,
        axisLine: { lineStyle: { color: group.color } },
        axisLabel: {
          formatter: (v) => {
            if (v >= 10000) return (v / 10000).toFixed(1) + '万'
            if (v >= 1000) return (v / 1000).toFixed(1) + 'k'
            return v
          },
        },
        max: maxVal > 0 ? Math.ceil(maxVal * 1.1) : 100,
        splitLine: { show: index === 0 },
      }
    }),
    series: metrics.map((metric, idx) => {
      const yAxisIndex = yAxisGroups.findIndex((g) => g.indices.includes(idx))

      return {
        name: metric.name,
        type: metric.name === '视频数' ? 'bar' : 'line',
        data: displayData.map((item) => item[metric.key]),
        smooth: true,
        yAxisIndex,
        lineStyle: { width: 2.5 },
        itemStyle: { radius: 4 },
        emphasis: { scale: true, itemStyle: { shadowBlur: 10 } },
        ...(metric.name === '视频数' && {
          itemStyle: {
            color: yAxisGroups[yAxisIndex].color,
            borderRadius: [4, 4, 0, 0],
          },
        }),
      }
    }),
    animation: true,
    animationDuration: 800,
  }

  myChart.setOption(option, true)
}

function playAnimation() {
  const data = allData[zone.value] || []
  const weeks = data.map((item) => item.week)
  let currentStep = 1
  clearInterval(timer)

  const intervalTime = 20
  timer = setInterval(() => {
    if (currentStep <= weeks.length) {
      renderChart(currentStep)
      currentStep++
    } else {
      clearInterval(timer)
    }
  }, intervalTime)
}

async function loadData() {
  const { data: res } = await http.get('/video/getDataWeekly', { params: { tid: zone.value } })
  if (res) {
    allData[zone.value] = res
    console.log('后端数据', res)
  } else {
    allData[zone.value] = []
    console.log('后端数据为空或格式不对', res)
  }
  playAnimation()
}

function onZoneChange() {
  if (myChart) myChart.clear()
  allData[zone.value] ? playAnimation() : loadData()
}

onMounted(() => {
  myChart = echarts.init(chart.value)
  loadData()
  window.addEventListener('resize', () => myChart?.resize())
  return () => {
    window.removeEventListener('resize', () => myChart?.resize())
    timer && clearInterval(timer)
    myChart && myChart.dispose()
  }
})

watch(
  () => allData[zone.value],
  () => myChart && playAnimation(),
)
</script>
